package com.cci.kangdao.utilTool;

import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.cci.kangdao.redis.RedisClientUtils;
import lombok.Data;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.NoSuchAlgorithmException;
import java.security.Security;
import java.util.Base64;
import java.util.Date;

/**
 * AES加密
 * W
 * @author Administrator
 */
@Component
@Data
public class AESTool {

	private static Logger log = Logger.getLogger(AESTool.class);
	private static final String IV_STRING = "Cty-china-ER-app";
	private static final String charset = "UTF-8";

	// 3.建一个静态的本类
	private static AESTool aesTool;

	// 4.初始化
	@PostConstruct
	public void init() {
		aesTool = this;
	}

	@Autowired
	private RedisClientUtils redisClientUtils;

	static{
		try{
			Security.addProvider(new BouncyCastleProvider());
		}catch(Exception e){
			e.printStackTrace();
		}
	}

	/**
	 * 加密
	 *
	 * @param content
	 *            需要加密的内容
	 * @param password
	 *            加密密码
	 * @return
	 */
	public static byte[] encrypt(String content, String password) {
		try {
			byte[] enCodeFormat = password.getBytes(charset);
			SecretKeySpec secretKeySpec = new SecretKeySpec(enCodeFormat, "AES");
			byte[] initParam = IV_STRING.getBytes(charset);
			IvParameterSpec ivParameterSpec = new IvParameterSpec(initParam);
			// 指定加密的算法、工作模式和填充方式
			Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
			cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);
			byte[] byteContent = content.getBytes(charset);
			byte[] result = cipher.doFinal(byteContent);
			return result; // 加密
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 加密
	 *
	 * @param content
	 *            需要加密的内容
	 * @param password
	 *            加密密码
	 * @return
	 */
	public static byte[] encryptNew(String content, String password) {
		try {
			byte[] enCodeFormat = password.getBytes(charset);
			SecretKeySpec secretKeySpec = new SecretKeySpec(enCodeFormat, "AES");
			byte[] initParam = IV_STRING.getBytes(charset);
			IvParameterSpec ivParameterSpec = new IvParameterSpec(initParam);
			// 指定加密的算法、工作模式和填充方式
			Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding","BC");
			cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);

			byte[] byteContent = content.getBytes(charset);
			byte[] result = cipher.doFinal(byteContent);
			return result; // 加密
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 解密
	 *
	 * @param content
	 *            待解密内容
	 * @param password
	 *            解密密钥
	 * @return
	 */
	public static byte[] decrypt(byte[] content, String password) {
		byte[] result = null;
		try {
			byte[] enCodeFormat = password.getBytes(charset);
			SecretKeySpec secretKey = new SecretKeySpec(enCodeFormat, "AES");
			byte[] initParam = IV_STRING.getBytes(charset);
			IvParameterSpec ivParameterSpec = new IvParameterSpec(initParam);
			Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
			cipher.init(Cipher.DECRYPT_MODE, secretKey, ivParameterSpec);
			result = cipher.doFinal(content);
			return result; // 加密
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 新解密方式
	 *
	 * @param content
	 *            待解密内容
	 * @param password
	 *            解密密钥
	 * @return
	 */
	public static byte[] decryptNew(byte[] content, String password) {
		byte[] result = null;
		try {
			byte[] enCodeFormat = password.getBytes(charset);
			SecretKeySpec secretKey = new SecretKeySpec(enCodeFormat, "AES");
			byte[] initParam = IV_STRING.getBytes(charset);
			IvParameterSpec ivParameterSpec = new IvParameterSpec(initParam);
			Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding", "BC");
			cipher.init(Cipher.DECRYPT_MODE, secretKey, ivParameterSpec);
			result = cipher.doFinal(content);
			return result; // 加密
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 将二进制转换成16进制
	 *
	 * @param buf
	 * @return
	 */
	public static String parseByte2HexStr(byte buf[]) {
		StringBuffer sb = new StringBuffer();
		for (int i = 0; i < buf.length; i++) {
			String hex = Integer.toHexString(buf[i] & 0xFF);
			if (hex.length() == 1) {
				hex = '0' + hex;
			}
			sb.append(hex.toUpperCase());
		}
		return sb.toString();
	}

	/**
	 * 将16进制转换为二进制
	 *
	 * @param hexStr
	 * @return
	 */
	public static byte[] parseHexStr2Byte(String hexStr) {
		if (hexStr.length() < 1) {
			return null;
		}
		byte[] result = new byte[hexStr.length() / 2];
		for (int i = 0; i < hexStr.length() / 2; i++) {
			int high = Integer.parseInt(hexStr.substring(i * 2, i * 2 + 1), 16);
			int low = Integer.parseInt(hexStr.substring(i * 2 + 1, i * 2 + 2), 16);
			result[i] = (byte) (high * 16 + low);
		}
		return result;
	}

	/**
	 * 加密ID
	 * @param content
	 * @return
	 */
	public static String encryptString(String content){
		byte[] encryptResult = new byte[]{};
		String cipherAES = (String) aesTool.redisClientUtils.getObject("cipherAES");
		if(StringUtils.isNotBlank(cipherAES)){
			encryptResult = encryptNew(content, "L03-Cumminschine");
		} else {
			encryptResult = encrypt(content, "L03-Cumminschine");
		}
		return parseByte2HexStr(encryptResult);
	}

	/**
	 * 解密ID
	 * @param content
	 * @return
	 */
	public static String decryptString(String content){
		try{
			String result = null;
			byte[] decryptFrom = parseHexStr2Byte(content);
			byte[] decryptResult = decrypt(decryptFrom, "L03-Cumminschine");
			if(null == decryptResult){
				decryptResult = decryptNew(decryptFrom, "L03-Cumminschine");
			}
			if(null != decryptResult){
				result = new String(decryptResult,charset);
			}
			return result;
		}catch(Exception ex){
			log.error(ex.getMessage(),ex);
		}
		return null;
	}

	/**
	 * medb   解密功能
	 */

	private static final String AES_ALGORITHM = "AES";
	private static final String AES_TRANSFORMATION = "AES/ECB/PKCS5Padding";
	private static final String MEDB_KEY = "cummins123456789";
	public static String medbDecrypt(String encryptedData) {
		Cipher cipher = null;
		try {
			cipher = Cipher.getInstance(AES_TRANSFORMATION);
			SecretKeySpec secretKeySpec = new SecretKeySpec(MEDB_KEY.getBytes(StandardCharsets.UTF_8), AES_ALGORITHM);
			cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);
			byte[] decryptedBytes = cipher.doFinal(Base64.getDecoder().decode(encryptedData));
			return new String(decryptedBytes, StandardCharsets.UTF_8);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	/**
	 * 测试
	 */
	public static void main(String[] args) throws Exception {
		Algorithm al = Algorithm.HMAC256("bdafbd92a7f3043c85e6e5450jdc722");
		System.out.println(JWT.create().withExpiresAt(new Date(System.currentTimeMillis() + 60 * 1000)).sign(al));
	}
}

